Kanzi Studio 插件扩展 Kanzi Studio 的功能并在 Kanzi Studio 中运行。 使用 Kanzi Studio 插件:
您可以在包含Kanzi Studio 插件用户界面的 Kanzi Studio 窗口中呈现插件,也可以将其作为用户可以从上下文菜单中执行的命令,在没有用户界面的情况下运行插件。本主题介绍如何创建 Kanzi Studio 命令插件。要了解如何创建 Kanzi Studio 窗口插件,请参阅 创建 Kanzi Studio 窗口插件。
Kanzi Studio 插件接口作为 .NET 框架程序集提供。您可以在 <KanziInstallation>/Studio/Bin/PluginInterface.dll 中找到它。插件接口可用于访问Kanzi Studio 中的数据和命令。When you want to use a Kanzi Studio plugin with different versions of Kanzi Studio, build the plugin with the PluginInterface.dll from each version of Kanzi Studio where you want to use that plugin.
要开发 Kanzi Studio 命令插件,请执行以下操作:
要查找有关 Kanzi Studio 插件接口的详细信息,请参阅:
您可在这里创建 Kanzi Studio 命令插件的基项,然后向其中添加功能来扩展 Kanzi Studio 的功能。
要创建 Kanzi Studio 命令插件:
System.ComponentModel.Composition
。在 Solution Explorer 中,右键点击工程名称,选择属性 (Properties),并:
Class1.cs
文件,并为 System.ComponentModel.Composition
和 Kanzi Studio 插件接口添加 using 指令:using System.ComponentModel.Composition; using Rightware.Kanzi.Studio.PluginInterface;
PluginCommand
界面的命令类之前,使用导出特性告诉 Kanzi Studio .dll 是一个插件。在本示例中,您在 Class1
类中实现该插件命令。[Export(typeof(PluginContent))]
Class1
用于实现 PluginCommand
界面的类,在 Class1
类中实现该界面。Kanzi 使用该类来创建此插件命令。public class Class1为
public class Class1 : PluginCommand
PluginCommand
界面。PluginCommand
, 上,点击 ,然后选择实现界面 (Implement Interface)。throw new NotImplementedException();
确保插件处理所有内部异常,不让它们传递到 Kanzi Studio 界面。
例如,设置Class1
类中的函数:CommandPlacement
函数设置插件的菜单名称以及在哪里显示命令以启动插件:ContextMenuPlacement.NONE
。ContextMenuPlacement.PROJECT_ITEM
。public CommandPlacement CommandPlacement { get { return new CommandPlacement("myPluginMenu", ContextMenuPlacement.NONE, false, null); } }
要在主菜单和上下文菜单中隐藏插件,请设置 CommandPlacement
函数返回 null
。
例如,当只想使用脚本运行 Kanzi Studio 命令来执行插件命令时,可以隐藏插件。请参阅 自动化 Kanzi Studio 任务。
public CommandPlacement CommandPlacement { get { return null; } }
Name
函数设置插件的内部名称。Kanzi 使用插件的内部名称,以便您在不对插件进行其他更改的情况下更改插件的显示名称。public string Name { get { return "Internal plugin name"; } }
DisplayName
函数在 Kanzi Studio 菜单中显示插件名称,您可以在其中启动插件。public string DisplayName { get { return "Plugin display name"; } }
Description
函数来设置 Kanzi Studio 插件内容的简要描述。用户将鼠标指针悬停在菜单中的插件名称上时,Kanzi Studio 会将本描述显示为工具提示。public string Description { get { return "A tooltip with short description of what the plugin does."; } }
CanExecute
函数设置用户能否启动插件以及在哪里启动插件:false
时,Kanzi Studio 在主菜单和上下文菜单中显示插件,但用户无法启动插件。true
时,用户可以启动插件。Kanzi Studio 为插件提供 KanziStudio
对象。KanziStudio
对象是数据访问的根对象,提供当前工程、可用命令、全局撤销和重做,以及与工程打开和关闭有关的事件。
例如,仅当 Kanzi Studio 工程打开时才使用此设置以启用命令
private KanziStudio studio; public bool CanExecute(PluginCommandParameter parameter) { return this.studio != null && this.studio.ActiveProject != null; }
Execute
函数添加您想要插件运行的代码。public void Execute(PluginCommandParameter parameter) { studio.Log("Hello world!"); }
Initialize
函数将 studio
置于成员变量中。public void Initialize(KanziStudio studio) { this.studio = studio; }
此处您创建了 Kanzi Studio 插件的基本结构,仅向 Kanzi Studio 日志 (Log) 窗口打印一条消息。要让插件进行更多操作,将您要让插件运行的代码添加到 Execute
函数。请参阅 向 Kanzi Studio 命令插件添加功能 和 向 Kanzi Studio 命令插件添加多个命令。
要进一步开发您的 Kanzi Studio 插件,请参阅 Kanzi Studio 插件接口概览和 Kanzi Studio 插件接口 API 参考。
要构建和运行 Kanzi Studio 插件:
将 Kanzi Studio 插件 .dll 复制到 %ProgramData%\Rightware\<KanziVersion>\plugins 目录。
如果 plugins 目录在 %ProgramData%\Rightware\<KanziVersion> 中不存在,请创建。
In Windows Explorer create a shortcut from your Kanzi Studio plugin dll file and move the shortcut to the %ProgramData%\Rightware\<KanziVersion>\plugins directory.
When you build the plugin, you can see in the Output window the location where Visual Studio stored the plugin dll file.
为 Kanzi Studio 命令插件创建基项后,向您的插件添加功能,以使其发挥作用。请创建一个插件,删除所有没有子节点的 空节点 (Empty Node) 节点。
要使用 Kanzi Studio 插件删除没有子节点的空节点 (Empty Node) 节点:
PluginCommand
界面的类库文件。Execute
函数中,编写当您调用插件命令时插件执行的代码。Execute
函数添加://插件执行此函数内容。将插件代码置于此处。 public void Execute(PluginCommandParameter parameter) { var items = parameter.Items; //打印到 Kanzi Studio 日志 (Log) 窗口。 studio.Log("Deleting all 空节点 (Empty Node) nodes without child nodes"); //从主菜单执行时,项传递空值作为参数。 //从上下文菜单执行时,项传递选定项作为参数 //(即使选择了多个项亦是如此)。 if (items != null && items.Any()) { // 如果从上下文菜单执行,启动从 //执行节点遍历场景图的函数。 TraverseTree(items); } else { //检查打开的工程。 if (studio != null && studio.ActiveProject!= null && studio.ActiveProject.Screen != null) { //如果从主菜单执行,启动 //从屏幕 (Screen) 节点的第一个子节点遍历场景图的函数。 TraverseTree(studio.ActiveProject.Screen.Children); } } } // TraverseTree 函数从启动插件的节点开始遍历场景图。 private void TraverseTree(IEnumerable<ProjectItem> items) { foreach (var item in items.ToArray()) { //如果节点为 2D 空节点 (Empty Node 2D) 或 3D 空节点 (Empty Node 3D) 并且没有 //任何子节点,则将其删除。 if ((item is EmptyNode2D || item is EmptyNode) && !item.Children.Any()) { //删除使用命令的工程项。这可让您 //撤销插件执行的动作。 studio.Commands.DeleteProjectItem(new ProjectItem[] { item }); } //遍历当前节点的子节点。 else if (item.Children.Any()) { TraverseTree(item.Children); } } }
CanExecute
函数中,设置在 Kanzi Studio 中调用此插件命令的方式和位置。public bool CanExecute(PluginCommandParameter parameter)
{
//只有选择了场景图中的单个节点时,才允许
//运行此插件命令。从主菜单执行插件时,调用零项,
//该操作将插件设置为开始从
//屏幕 (Screen) 节点的第一个子节点遍历场景图。
var items = parameter.Items;
return items != null && items.Count() <= 1;
}
要进一步开发您的 Kanzi Studio 插件,请参阅 Kanzi Studio 插件接口概览和 Kanzi Studio 插件接口 API 参考。
为 Kanzi Studio 命令插件创建基项后,向您的插件添加功能。您可以创建一个 Kanzi Studio 命令插件,实现多个命令。请创建一个包含以下命令的插件:
该插件查找并移除活动工程中,指向同一工程中或已加载的引用工程中资源的无效 kzb URL。
要记录 Kanzi Studio 工程中的无效 kzb URL,请执行以下操作:
InvalidKzbUrlFinder
”的 Visual Studio 工程,具有一个名为 ListInvalidKzbUrls
的类,该类可实现 PluginCommand
界面 :using System.ComponentModel.Composition; using Rightware.Kanzi.Studio.PluginInterface; namespace InvalidKzbUrlFinder { [Export(typeof(PluginContent))] public class ListInvalidKzbUrls : PluginCommand { private KanziStudio studio; public void Initialize(KanziStudio studio) { this.studio = studio; } //在 Kanzi Studio 主菜单中,显示名为“Kzb URL 检查器”的插件命令。 public CommandPlacement CommandPlacement => new CommandPlacement("Kzb URL Checker", ContextMenuPlacement.NONE, false, null); //设置该插件命令的内部名称。此函数使您无需额外更改插件,即可更改命令的显示名称。 public string Name => "LogInvalidKzbUrls"; //设置 Kanzi Studio 主菜单中的命令名。 public string DisplayName => "Log Invalid Kzb URLs"; //设置命令的工具提示。 public string Description => "Prints to the 日志 (Log) the invalid kzb URLs in the active project."; public bool CanExecute(PluginCommandParameter parameter) { return studio?.ActiveProject != null; } } }
PluginCommand
界面的类中,添加从资源的 kzb URL 获取包含该资源的工程名称的函数。public static Project GetProjectFromKzbUrl(Solution solution, string urlCandidate) { Project result = null; foreach (var project in solution.Projects) { var projectName = project.Name.Replace(" ", "_").ToLowerInvariant(); if (urlCandidate?.StartsWith("kzb://" + projectName) == true) { result = project; break; } } return result; } public Project GetProjectFromKzbUrl(string urlCandidate) { return GetProjectFromKzbUrl(studio.Solution, urlCandidate); }
System.Linq
命名空间添加使用指令。Enumerable.Where
方法。using System.Linq;
PluginCommand
界面的类中,添加一个函数检查 kzb URL 是否指向现有资源。public static bool IsValidKzbUrl(Solution solution, Project project, string kzbUrl) { var result = false; if (GetProjectFromKzbUrl(solution, kzbUrl) == project) { var projectNameInKzbFormat = project.Name.Replace(" ", "_").ToLowerInvariant(); var itemPath = kzbUrl.Substring(("kzb://" + projectNameInKzbFormat + "/").Length); ProjectItem currentItem = project; var parts = itemPath.Split('/').Where(x => !string.IsNullOrEmpty(x)); foreach (var part in parts) { currentItem = currentItem.GetChild(part); if (currentItem == null) { break; } } result = currentItem != null; } return result; }
PluginCommand
界面的类中,添加一个函数,打印无效 kzb URL 到 日志 (Log)。private int LogKzbUrls(ProjectItem item, int count) { foreach (var projectItem in item.Children) { var properties = projectItem.Properties; foreach (var property in properties) { var propertyValue = projectItem.Get(property); var nodeResource = propertyValue as ResourceReferenceBase; if (nodeResource != null) { var project = GetProjectFromKzbUrl(nodeResource.ResourceID); if (project != null && !IsValidKzbUrl(studio.Solution, project, nodeResource.ResourceID)) { studio.Log($"Invalid kzb URL \"{nodeResource}\" found in the \"{property.DisplayName}\" property of \"{projectItem.Path ?? projectItem.Name}\"."); count++; } } } count = LogKzbUrls(projectItem, count); } return count; }
PluginCommand
界面的类的 Execute
函数中,写入调用该插件命令时插件执行的代码。 public void Execute(PluginCommandParameter parameter)
{
studio.Log("Finding invalid kzb URLs...");
//调用打印无效 kzb URL 到 日志 (Log) 的函数。
var count = LogKzbUrls(studio.ActiveProject, 0);
studio.Log($"This project contains {count} invalid kzb URLs.");
}
要从 Kanzi Studio 工程中移除无效 kzb URL,请执行以下操作:
PluginCommand
界面。RemoveInvalidKzbUrls
”的类:using System.ComponentModel.Composition; using Rightware.Kanzi.Studio.PluginInterface; namespace InvalidKzbUrlFinder { [Export(typeof(PluginContent))] class RemoveInvalidKzbUrls : PluginCommand { private KanziStudio studio; public void Initialize(KanziStudio studio) { this.studio = studio; } //在 Kanzi Studio 主菜单中,显示名为“Kzb URL 检查器”的插件命令。 public CommandPlacement CommandPlacement => new CommandPlacement("Kzb URL Checker", ContextMenuPlacement.NONE, false, null); //设置该插件命令的内部名称。此函数使您无需额外更改插件,即可更改命令的显示名称。 public string Name => "RemoveInvalidKzbUrls"; //设置 Kanzi Studio 主菜单中的命令名。 public string DisplayName => "Remove Invalid Kzb URLs"; // Set the tooltip for the command. public string Description => "Removes the invalid kzb URLs from the active project."; public bool CanExecute(PluginCommandParameter parameter) { return studio?.ActiveProject != null; } public void Execute(PluginCommandParameter parameter) { throw new NotImplementedException(); } } }
private int RemoveKzbUrls(ProjectItem item, int currentCount) { foreach (var projectItem in item.Children) { var properties = projectItem.Properties; foreach (var property in properties) { var propertyValue = projectItem.Get(property); var nodeResource = propertyValue as ResourceReferenceBase; if (nodeResource != null) { var project = ListInvalidKzbUrls.GetProjectFromKzbUrl(studio.Solution, nodeResource.ResourceID); if (project != null && !ListInvalidKzbUrls.IsValidKzbUrl(studio.Solution, project, nodeResource.ResourceID)) { projectItem.Set(property.Name, null); currentCount++; } } } currentCount = RemoveKzbUrls(projectItem, currentCount); } return currentCount; }
Execute
函数中,编写当您调用插件命令时插件执行的代码。public void Execute(PluginCommandParameter parameter) { studio.Log("Removing invalid kzb URLs..."); //调用移除无效 kzb URL 的函数。 var removedCount = RemoveKzbUrls(studio.ActiveProject, 0); studio.Log($"Removed {removedCount} invalid kzb URLs from the project."); }
要进一步开发您的 Kanzi Studio 插件,请参阅 Kanzi Studio 插件接口概览和 Kanzi Studio 插件接口 API 参考。